package x.ovo.wechat.bot.core;


import cn.hutool.core.thread.ThreadUtil;
import lombok.extern.slf4j.Slf4j;
import x.ovo.wechat.bot.common.Context;
import x.ovo.wechat.bot.common.entity.SyncCheckResult;
import x.ovo.wechat.bot.common.entity.WebSyncResult;
import x.ovo.wechat.bot.common.entity.event.LogoutSystemEvent;
import x.ovo.wechat.bot.common.entity.message.RawMessage;
import x.ovo.wechat.bot.common.enums.SyncCheckRetCode;
import x.ovo.wechat.bot.common.enums.SyncCheckSelector;
import x.ovo.wechat.bot.common.http.WechatApi;
import x.ovo.wechat.bot.http.OkCookieJar;
import x.ovo.wechat.bot.login.HotReload;

import java.time.Instant;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 轮询监听消息
 *
 * @author ovo, created by 2024/04/21
 */
@Slf4j
public class ChatLoop implements Runnable {

    private final Context context;
    private final WechatApi api;
    private int retryCount = 0;
    private final Config config = Config.get();

    public ChatLoop(Context context) {
        this.context = context;
        this.api = context.getApi();
    }

    @Override
    public void run() {
        log.info("心跳检测线程已启动");
        while (this.context.isRunning()) {
            if (!this.context.isLogin()) {
                ThreadUtil.safeSleep(TimeUnit.SECONDS.toMillis(5));
                continue;
            }
            try {
                // 同步检查，如果状态正常，则处理正常状态、拉取新消息，否则抛出异常重新登录
                SyncCheckResult response = this.api.syncCheck();
                if (SyncCheckRetCode.NORMAL.equals(response.getRetCode())) {
                    handleNormal(response);
                } else {
                    throw new RuntimeException("同步状态异常：" + response.getRetCode().getMessage());
                }
            } catch (Exception e) {
                this.context.setLogin(false);
                log.error("同步异常: {}", e.getMessage(), e);
                HotReload.build(this.context.getLoginSession(), OkCookieJar.getCookieStore()).save();
                if (this.retryCount <= this.config.getRetryCount()) {
                    this.retryCount++;
                    log.warn("重试第 {} 次...", retryCount);
                    ThreadUtil.safeSleep(TimeUnit.SECONDS.toMillis(this.retryCount * 10L));
                    this.api.login(true);
                    if (this.context.isLogin()) this.retryCount = 0;
                } else {
                    log.warn("心跳同步异常, 重试次数达到上限, 退出登录");
                    this.api.logout();
                    this.context.getEventManager().callEvent(new LogoutSystemEvent("心跳同步异常"));
                }
            }
        }
    }

    /**
     * 处理同步状态正常的
     *
     * @param syncCheck 同步检查
     */
    private void handleNormal(SyncCheckResult syncCheck) {
        // 更新最后一次正常检查时间
        this.context.setLastSyncCheckTime(Instant.now().toEpochMilli());
        if (SyncCheckSelector.NORMAL.equals(syncCheck.getRetSelector())) {
            return;
        }
        // 获取消息
        WebSyncResult result = this.api.webSync();
        // 更新同步key
        if (result.getSyncKey().getCount() > 0) this.context.getLoginSession().setSyncKey(result.getSyncKey());
        if (result.getSyncCheckKey().getCount() > 0)
            this.context.getLoginSession().setSyncCheckKey(result.getSyncCheckKey());
        // 获取消息列表
        List<RawMessage> rawMessageList = result.getAddMsgList();
        if (rawMessageList != null && !rawMessageList.isEmpty()) {
            MessageConsumer.addMessages(rawMessageList);
        }
    }
}
